<?php

class protoType {
	protected $rh;
	protected $store;

	protected $object;
	protected $fields = array();
	protected $title_field = '';
	protected $text;
	protected $title_text;
	protected $parent_oid = 0;

	public function __construct( $rh, $store ) {
		$this->rh = $rh;
		$this->store = $store;
	}

	public function linkToObject( $oid ) {
		$this->object = $this->store->getObject($oid);
	}

	public function linkFromObject( $obj ) {
		$this->object = $obj;
	}

	public function prepareText() {
		$this->text = $this->getParsedText();
		$this->title_text = $this->getParsedTitle();
	}

	private function getParsedText() {
		if ( !($this->object instanceof fobject) ) {
			return false;
		}
	
		if ( !isset($this->object->data) ) {
			return false;
		}
	
		$text = $this->concatFields();
		
		return $this->parseText($text);
	}
	
	private function getParsedTitle() {
		if ( !($this->object instanceof fobject) ) {
			return false;
		}
	
		if ( !isset($this->object->data) ) {
			return false;
		}
	
		$text = $this->getTitle();
		
		return $this->parseText($text);
	}

	protected function concatFields() {
		$text = '';
		$data = $this->object->data;
		
		foreach ( $this->fields as $field ) {
			if ( isset($data[$field]) && !empty($data[$field]) ) {
				$text .= " {$data[$field]}";
			}
		}
		
		return $text;
	}
	
	protected function getTitle() {
		$title = '';
		
		if ( !empty($this->title_field) && isset($this->object->data[$this->title_field]) ) {
			$title = $this->object->data[$this->title_field];
		}
		
		return $title;
	}

	private function parseText( $text ) {
		mb_language('ru');
		mb_internal_encoding("UTF-8");
		mb_detect_order(array('UTF-8','WINDOWS-1251'));
		mb_regex_encoding('UTF-8');
		setlocale(LC_CTYPE, array("ru_RU.UTF-8","ru_RU","russian","ru_SU","ru"));
		
		$text = mb_strtolower($text);
		$text = strip_tags( $text );
		
		$text = mb_ereg_replace( '\&[\w\d]+\;', ' ', $text );
		$text = mb_ereg_replace( '[\W\d_]+', ' ', $text );
		
		$text = mb_ereg_replace( '(\b\w{1,3}\b)', ' ', $text );

		$text = mb_ereg_replace( '^\s+', '', $text );
		$text = mb_ereg_replace( '\s+$', '', $text );
		$text = mb_ereg_replace( '\s+', ' ', $text );

		return $text;
	}

	public function getParsedWords( $text ) {
		$allWords = explode( ' ', $text );
		
		$words = array();
		foreach ( $allWords as $word ) {
			if ( isset($words[$word]) ) {
				$words[$word]++;
			} else {
				$words[$word] = 1;
			}
		}

		return $words;
	}

	public function makeSearchData( $oid ) {
		$this->prepareText();
		$md5_crc = md5($this->text);

		$db_record = $this->store->query('select * from se_indexed where oid = ' . $oid)->next();

		$this->store->db->begin();
		
		if ( !empty($db_record) ) {
			if ( $md5_crc == $db_record['md5_crc'] ) {
				$this->store->db->end();
				return true;
			} else {
				$result = $this->store->query("update se_indexed " .
				" set md5_crc = '{$md5_crc}' where oid = {$oid}");
				if ( !($result instanceof MysqlDBResult) ) {
					$this->store->db->rollback();
					return false;
				}
			}
		} else {
			$result = $this->store->query('insert into se_indexed (oid, parent_oid, md5_crc) ' .
			" values({$oid}, {$this->parent_oid}, '{$md5_crc}')" );
			if ( !($result instanceof MysqlDBResult) ) {
				$this->store->db->rollback();
				return false;
			}
		}

		$result = $this->removeObjectFromCrossTable($oid);
		
		if ( !$result ) {
			$this->store->db->rollback();
			return false;
		}
		
		$words = $this->getParsedWords( $this->text );
		$title_words = $this->getParsedWords( $this->title_text );
		
		foreach ( $words as $word=>$rel ) {
			if ( empty($word) ) {
				continue;
			}
			$word_esc = $this->store->db->quote($word);
			$inWords = $this->store->query("select id, group_id from se_words " .
			" where name = {$word_esc}")->next();

			if ( empty($inWords) ) {
				list( $word_id, $group_id ) = $this->pushInWordsTable( $word_esc );
				if ( false === $word_id ) {
					$this->store->db->rollback();
					return false;
				}
			} else {
				$word_id = $inWords['id'];
				$group_id = $inWords['group_id'];
			}

			if ( isset($title_words[$word]) ) {
				$isTitle = 1;
			} else {
				$isTitle = 0;
			}

			$result = $this->store->query("insert into se_x (word_id, oid, rel, title) " .
			" values ({$word_id}, {$oid}, {$rel}, {$isTitle})");
			if ( !($result instanceof MysqlDBResult) ) {
				$this->store->db->rollback();
				return false;
			}
		}

		$this->store->db->end();
		return true;
	}

	private function getLastID() {
		$last = $this->store->query('select last_insert_id() as last_id')->next();
		if ( !empty($last) ) {
			return $last['last_id'];
		} else {
			return 0;
		}
	}

	private function pushInWordsTable( $word_esc ) {
		$group_id = 0;

		$inPreWords = $this->store->query("select group_id from se_pre_words " .
		" where word = {$word_esc}")->next();
		if ( !empty($inPreWords) ) {
			$group_id = $inPreWords['group_id'];
		}

		$result = $this->store->query("insert into se_words (name, group_id) " .
		" values ({$word_esc}, {$group_id})");
		if ( !($result instanceof MysqlDBResult) ) {
			return array( false, false );
		}

		$word_id = $this->getLastID();

		return array( $word_id, $group_id );
	}

	private function removeObjectFromCrossTable( $oid ) {
		$result = $this->store->query("delete from se_x where oid = {$oid}");
		if ( !($result instanceof MysqlDBResult) ) {
			return false;
		}
		return true;
	}

	public function cleanWords() {
		$result = $this->store->query('select x.oid from se_x x ' .
		' left join se_indexed i on i.oid = x.oid ' .
		' where isnull(i.oid) group by oid');
		if ( !($result instanceof MysqlDBResult) ) {
			return false;
		}

		while ( $rec = $result->next() ) {
			$res = $this->store->query("delete from se_x where oid = {$rec['oid']}");
		}

		$result = $this->store->query("select w.id from se_words w " .
		" left join se_x x on x.word_id = w.id " .
		" where isnull(x.word_id) group by w.id");
		if ( !($result instanceof MysqlDBResult) ) {
			return false;
		}

		while ( $rec = $result->next() ) {
			$this->store->query("delete from se_words where id = {$rec['id']}");
		}

		return true;
	}

	public function deleteItem($oid) {
		$this->store->query("delete from se_indexed where oid = {$oid}");
	}
}